package services

import (
	"fmt"
	"strconv"
	"time"

	"cashew.com/cashew_common/configs"
	"cashew.com/cashew_common/utils"
	"cashew.com/cashew_task/dtos"
	"github.com/beego/beego/v2/core/logs"
)

func AnchorWorkStatsDay() error {
	location, err := time.LoadLocation(configs.DefaultTimezone)

	if err != nil {
		logs.Error("加载时区失败")
		return err
	}

	t := time.Unix(utils.GetNowTimestamp()-86400, 0)

	year := t.In(location).Year()   // 统计的年份
	month := t.In(location).Month() // 统计的月份
	day := t.In(location).Day()     // 统计的日期

	startTime := time.Date(year, month, day, 0, 0, 0, 0, location).Unix()
	endTime := time.Date(year, month, day, 23, 59, 59, 0, location).Unix()

	page := utils.PageQuery{
		Page: 0,
		Size: 50,
	}

	statModel := dtos.AnchorWorkStatsDay{}

	workTypeMapping := configs.WorkTypeMapping
	statFields := ""
	for key, val := range workTypeMapping {
		statFields += fmt.Sprintf("SUM(CASE WHEN type = %d THEN value ELSE 0 END) AS `%s`,", key, val)
	}
	statFields = statFields[:len(statFields)-1]

	insertSql := "INSERT INTO anchor_work_stats_day_%d" +
		" (anchor_id, date_key, week_key, month_key, online_time, incoming_call_count, incoming_call_answered_count, call_count, " +
		"call_answered_count, call_income, gift_income, chat_unlock_count, create_time, update_time) " +
		"VALUES (:anchor_id, :date_key, :week_key, :month_key, :online_time, :incoming_call_count, :incoming_call_answered_count, " +
		":call_count, :call_answered_count, :call_income, :gift_income, :chat_unlock_count, :create_time, :update_time)"

	db := utils.GetDB()
	statDb := utils.GetStatDB()

	for i := 0; i < 1000; i++ {
		page.Page++

		sql := "select anchor_id from anchor_work_stats where hour_id >= ? and hour_id <= ? group by anchor_id order by anchor_id limit ?,?"

		rows, dbErr := db.Query(sql, startTime, endTime, page.GetOffset(), page.GetLimit())

		if dbErr != nil {
			logs.Error("第%d次查询主播列表失败:err=%s", i, dbErr.Error())
			break
		}

		var anchorIdList []int64
		for rows.Next() {
			var anchorId int64
			rows.Scan(&anchorId)
			anchorIdList = append(anchorIdList, anchorId)
		}

		rows.Close()

		if len(anchorIdList) == 0 {
			logs.Error("第%d查询主播列表数据为空", i)
			break
		}

		for _, anchorId := range anchorIdList {

			statModel = dtos.AnchorWorkStatsDay{}
			anchorInfoSql := fmt.Sprintf("select %s from anchor_work_stats where hour_id >= ? and hour_id <= ? and anchor_id = ? group by anchor_id limit 1", statFields)

			anchorInfoRows, dbAnchorInfoErr := db.Query(anchorInfoSql, startTime, endTime, anchorId)

			if dbAnchorInfoErr != nil {
				logs.Error("查询主播小时统计数据失败", dbAnchorInfoErr.Error())
				continue
			}

			for anchorInfoRows.Next() {
				anchorInfoRows.Scan(&statModel)
			}

			anchorInfoRows.Close()

			statModel.AnchorId = anchorId
			statModel.DateKey = fmt.Sprintf("%d-%02d-%02d", year, month, day)
			statModel.MonthKey = fmt.Sprintf("%d-%02d-01", year, month)
			statModel.WeekKey = utils.GetWeekdayFormat(startTime, 1, "2006-01-02")
			statModel.CreateTime = utils.GetNowTimestamp()
			statModel.UpdateTime = statModel.CreateTime

			_, insertErr := statDb.NamedExec(fmt.Sprintf(insertSql, year), statModel)

			if insertErr != nil {
				logs.Error("写入主播(%d)日统计数据失败:err=%s", anchorId, insertErr.Error())
				continue
			}

			//如果周一和周日不在同一年表示这个星期是跨年那一周，需要分别写入两个表
			if statModel.WeekKey[:4] != utils.GetWeekdayFormat(startTime, 7, "2006") {
				if statModel.WeekKey[:4] == strconv.Itoa(year) {
					//如果当天和周一在同一年, 则写入周日对应的下一年表
					_, insertErr = statDb.NamedExec(fmt.Sprintf(insertSql, year+1), statModel)
					if insertErr != nil {
						logs.Error("写入主播(%d)日统计数据(year+1)失败:err=%s", anchorId, insertErr.Error())
						continue
					}
				} else {
					//如果当天和周一不在同一年, 则写入周一对应的上一年表
					_, insertErr = statDb.NamedExec(fmt.Sprintf(insertSql, year-1), statModel)
					if insertErr != nil {
						logs.Error("写入主播(%d)日统计数据(year-1)失败:err=%s", anchorId, insertErr.Error())
						continue
					}
				}
			}
		}
	}

	return err
}
